/**
 * @file		dd_pmc_ctc.c
 * @brief		PMC CTC (Cycle Time Counter) driver
 * @note		None
 * @attention	None
 * 
 * <B><I>Copyright 2016 Socionext Inc.</I></B>
 */

#include "dd_pmc_ctc.h"
#include "pmc.h"

/*----------------------------------------------------------------------*/
/* Definition															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special


/*----------------------------------------------------------------------*/
/* Enumeration															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special


/*----------------------------------------------------------------------*/
/* Structure															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special


/*----------------------------------------------------------------------*/
/* Global Data															*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Callback function pointer
static volatile VP_CALLBACK			gDD_PMC_CTC_Callback	= NULL;

/*----------------------------------------------------------------------*/
/* Macro																*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special


/*----------------------------------------------------------------------*/
/* Local Function														*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
// Nothing Special


static VOID Dd_pmc_ctc_callback(VOID)
{
#ifdef CTC_COUNT_DOWN_USAGE
	UCHAR status=0;
	ULONG count = 0;

	if(D_DDIM_OK == Dd_PMC_CTC_Get_Measuring_End_Status(&status))
	{
		// register data output.
		Ddim_Print(("--- CTC Register ---\n"));
		Ddim_Print(("INTSTAT : 0x%08lx\n", IO_PMC.CTC.INTSTAT.word));
		// get data output.
		Ddim_Print(("--- Get data -------\n"));
		Ddim_Print(("status  : %d\n", status));
		if(D_DDIM_OK == Dd_PMC_CTC_Get_Counter_Value(&count)) {
			Ddim_Print(("count=%lu\n"));
		}
		Ddim_Print(("--------------------\n"));
	}
#else
	Ddim_Print(("Dd Callback\n"));
#endif
}
/*----------------------------------------------------------------------*/
/* Grobal Function														*/
/*----------------------------------------------------------------------*/
//---------------------------- driver section ----------------------------
/**
 * @brief  Set control data.
 * @param[in]	ctrl	CTC control data.<br>
 * @retval	D_DDIM_OK						Success.
 * @retval	D_DD_PMC_CTC_INPUT_PARAM_ERR	Input parameter error.
 */
INT32 Dd_PMC_CTC_Ctrl( T_DD_PMC_CTC_Ctrl const* const ctrl )
{
	union io_pmc_ctc_intctl	intctl;
#ifdef CO_PARAM_CHECK
	if( ctrl == NULL ){
		Ddim_Assertion(("Dd_PMC_CTC_Ctrl: input param error is NULL.\n"));
		return D_DD_PMC_CTC_INPUT_PARAM_ERR;
	}
#endif
	
	// Set Interrupt Control
	intctl.word	= 0;
	intctl.bit.MEIE = ctrl->interrupt_enable;
	intctl.bit.SWFI = ctrl->select_wait;
	IO_PMC.CTC.INTCTL.word = intctl.word;					/* pgr0872 */
	
	// Set Observed Clock Length
	IO_PMC.CTC.OBCLEN.word = ctrl->clock_length;
	
	return D_DDIM_OK;
}

/**
 * @brief  Measurement start.
 * @param[in]	callback			callback function pointer.<br>
 * @retval	D_DDIM_OK						Success.
 * @retval	D_DD_PMC_CTC_MACRO_BUSY_NG		CTC module busy.
 */
INT32 Dd_PMC_CTC_Start( VP_CALLBACK callback )
{
	// check module status
	if (IO_PMC.CTC.CTL.bit.TRG == 1) {
		// Busy
		return D_DD_PMC_CTC_MACRO_BUSY_NG;
	}

	// Set callback
	if(!callback) {
		gDD_PMC_CTC_Callback = (VP_CALLBACK)Dd_pmc_ctc_callback;
	}
	else {
		gDD_PMC_CTC_Callback = callback;
	}
	
	// Clear Interrupt status
	IO_PMC.CTC.INTSTAT.word = 0;
	
	// Measurement start
	IO_PMC.CTC.CTL.word = 1;

	return D_DDIM_OK;
}

/**
 * @brief  Measuring End Interrupt request.
 * @param[out]	status		Measuring end interrupt status.
 * @retval	D_DDIM_OK						Success.
 * @retval	D_DD_PMC_CTC_INPUT_PARAM_ERR	Input parameter error.
 */
INT32 Dd_PMC_CTC_Get_Measuring_End_Status( UCHAR* status )
{
#ifdef CO_PARAM_CHECK
	if( status == NULL ){
		Ddim_Assertion(("Dd_PMC_CTC_Get_Measuring_End_Status: input param error is NULL.\n"));
		return D_DD_PMC_CTC_INPUT_PARAM_ERR;
	}
#endif
	
	// Get INTSTAT.MEST
	*status = IO_PMC.CTC.INTSTAT.bit.MEST;
	
	return D_DDIM_OK;
}

/**
 * @brief  Get Counter value.
 * @param[out]	counter_value		counted value of the measuring.
 * @retval	D_DDIM_OK						Success.
 * @retval	D_DD_PMC_CTC_INPUT_PARAM_ERR	Input parameter error.
 */
INT32 Dd_PMC_CTC_Get_Counter_Value( ULONG* counter_value )
{
#ifdef CO_PARAM_CHECK
	if( counter_value == NULL ){
		Ddim_Assertion(("Dd_PMC_CTC_Get_Counter_Value: input param error is NULL.\n"));
		return D_DD_PMC_CTC_INPUT_PARAM_ERR;
	}
#endif

	// Get Counter Value
	*counter_value	= IO_PMC.CTC.CNTVAL;

	return D_DDIM_OK;
}

/**
 * @brief  Interrupt Handler.
 */
VOID Dd_PMC_CTC_Int_Handler( VOID )
{
	if (IO_PMC.CTC.INTSTAT.bit.MEST == 1) {
		// Clear Interrupt status
		IO_PMC.CTC.INTSTAT.word = 0;
		
		if (gDD_PMC_CTC_Callback != NULL) {
			(*gDD_PMC_CTC_Callback)();		// Call Back function
		}
	}
}

